package com.laity.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author: Laity
 * @Project: JavaLaity
 * @Package: com.laity.cas.AbaDemo
 * @Date: 2023年12月15日 10:26
 * @Description: 复现 CAS-ABA问题并 解决(乐观锁原理)
 */

public class AbaDemo {

    public static void main(String[] args) {
        // AtomicInteger atomicInteger = new AtomicInteger(2023);
        // 使用原子引用
        // new AtomicReference<>() // 基本的原子引用

        // AtomicStampedReference(V initialRef, int initialStamp)  初始值和初始时间戳
        // 携带时间戳的原子引用 这个时间戳就相当于版本号，每次修改值的时候，时间戳都会加1
        // TODO: Integer使用了对象缓存机制，默认范围是-128到127，超过范围会自动装箱，导致引用不同，导致交换失败
        //  推荐使用静态工厂方法valueOf()获取对象实例，而不是new 因为valueOf()使用缓存，而new一定会创建新的对象分配新的内存空间
        //  new AtomicStampedReference<>(2023, 123) 将2023改小些就不会出现问题了。 正常业务操作比较的是一个对象
        AtomicStampedReference<Integer> reference = new AtomicStampedReference<>(1, 1);
        // 自动装箱导致引用不同，导致交换失败


        new Thread(() -> {
            int stamp = reference.getStamp(); // 获取时间戳
            System.out.println("t1获取时间戳：" + stamp);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(reference.compareAndSet(1, 2, reference.getStamp(), reference.getStamp() + 1));
            System.out.println("t1修改后的时间戳：" + reference.getStamp());

            System.out.println(reference.compareAndSet(2, 1, reference.getStamp(), reference.getStamp() + 1));

            System.out.println("t1最后修改后的时间戳：" + reference.getStamp());
        }, "t1").start();

        new Thread(() -> {
            int stamp = reference.getStamp(); // 获取时间戳
            System.out.println("t2获取时间戳：" + stamp);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(reference.compareAndSet(1, 3, reference.getStamp(), reference.getStamp() + 1));
            System.out.println("t2值：" + reference.getStamp());
        }, "t2").start();

//        // ===========================捣乱的线程===========================
//        System.out.println(atomicInteger.compareAndSet(2023, 2024));
//        System.out.println(atomicInteger.get());
//
//        System.out.println(atomicInteger.compareAndSet(2024, 2023));
//        System.out.println(atomicInteger.get());
//
//        // ===========================期望的线程===========================
//        System.out.println(atomicInteger.compareAndSet(2023, 2025));
//        System.out.println(atomicInteger.get());
    }
}
